import recommend
import os
import pandas as pd
from dsjxtjc_mysql import mmySQL

# 接口run(people_num:int, old_list:list) people_num为人数，old_list为倾向要点的菜品。 返回有20个list的list，每个list为一份菜单
class Node:
    def __init__(self, uid = '0', parent = None):
        self.parent = parent
        self.children = []
        self.times = 0
        self.id = uid
        self.line_num = 0
    def __str__(self):
        return self.id
    def search(self, uid):
        for child in self.children:
            if child.id == uid:
                return child
        return None
    def insert(self, child):
        self.children.append(child)

def build_tree(data, dlist):
    root = Node()
    uid_nodes = {}
    for d in dlist:
        uid_nodes[d] = []
    for line in data:
        curr = root
        for d in dlist:
            if d in line:
                n = curr.search(d)
                if not n:
                    n = Node(d, curr)
                    curr.insert(n)
                    uid_nodes[d].append(n)
                n.times += 1
                curr = n
    keys = dlist.copy()
    keys.reverse()
    return root, uid_nodes

def filter_list(result_list, food_num, people_num):
    result = []
    final_result = []
    max_len = 0
    for rc in result_list:
        max_len = len(rc[1]) if len(rc[1]) > max_len else max_len
        rl = rc[1]
        real = [0 for _ in range(10)]
        match = True
        for r in rl:
            real[int(r[:2]) - 1] += 1
        for i in range(8):
            if real[i] < 1:
                match = False
                break
        if len(rl) < 3 * people_num:
            match = False
        if match:
            result.append(rc)
        else:
            #print(real)
            pass
    for rc in result:
        tr = []
        real = [0 for _ in range(10)]
        for i in range(8):
            real[i] = int(food_num[i])
        rl = rc[1]
        rl.reverse()
        for r in rl:
            if real[int(r[:2]) - 1] != 0:
                tr.append(r)
                real[int(r[:2]) - 1] -= 1
        exist = False
        for fr in final_result:
            if fr[0] == tr:
                exist = True
                fr[1] = fr[1] if fr[1] > rc[1] else rc[1]
        if not exist:
            final_result.append([tr, rc[1]])
    print(max_len)
    return final_result

def fp_recommend(root, uid_nodes, people_num, food_type_num = None, curr_list = None):
    dlist = list(uid_nodes.keys())
    result = []
    stack = []
    if not curr_list.empty:
        curr_list = ['0']
    keys = dlist.copy()
    keys.reverse()
    tlist_sort = []
    result = []
    for k in keys:
        if k in curr_list:
            tlist_sort.append(k)
    #print(tlist_sort)
    k = tlist_sort[0]
    lowest_nodes = []
    p = uid_nodes[k]
    for q in p:
        r = q
        end = True
        for index in range(1, len(tlist_sort)):
            if r == None:
                end = False
                break
            while r != None:
                if r.id == tlist_sort[index]:
                    break
                r = r.parent
        if end:
            stack.append(q)
    while stack:
        curr = stack[-1]
        stack.pop()
        if not curr.children:
            lowest_nodes.append(curr)
        else:
            lowest_nodes.append(curr)
            for child in curr.children:
                stack.append(child)
    for l in lowest_nodes:
        cr = []
        m = l
        while m.parent != None:
            cr.append(m.id)
            m = m.parent
        result.append([l.times, cr])
    result.sort(reverse=True)
    result = filter_list(result, food_type_num, people_num)
    if len(result) > 20:
        result = result[:20]
    return result

def save_fp_tree(root, uid_nodes, file_path="./data/fp_tree.txt", filter_num = 3):
    fout = open(file_path, "w")
    s = []
    s.append(root)
    line_num = 0
    keys = uid_nodes.keys()
    fout.write("---keys---\n")
    for k in keys:
        fout.write("%s\n" % k)
    fout.write("---nodes---\n")
    while s:
        p = s[-1]
        s.pop()
        if p.id != '0' and p.times < filter_num:
            continue
        p.line_num = line_num
        line_num += 1
        pid = 'None' if p.parent == None else p.parent.id
        plnum = -1 if p.parent == None else p.parent.line_num
        fout.write("%s %d %s %d\n" % (p.id, p.times, pid, plnum))
        for c in p.children:
            s.append(c)
    fout.close()

def load_fp_tree(file_path="./data/fp_tree.txt"):
    fin = open(file_path, "r")
    nodes = []
    lines = fin.readlines()
    root = None
    uid_nodes = {}
    uid_nodes['0'] = []
    mode = None
    for line in lines:
        line = line[:-1]
        if line == "---keys---":
            mode = "key"
            continue
        if line == "---nodes---":
            mode = "node"
            continue
        if mode == "key":
            uid_nodes[line] = []
        if mode == "node":
            cells = line.split()
            c = None
            if cells[2] == 'None': #根节点
                root = Node(cells[0])
                c = root
            else:
                p = nodes[int(cells[3])]
                c = Node(cells[0], p)
                c.times = int(cells[1])
                p.insert(c)
            uid_nodes[c.id].append(c)
            nodes.append(c)
    fin.close()
    return root, uid_nodes

    
def preprocess_data(data):
    dcount = {}
    for line in data:
        for cell in line:
            try:
                dcount[cell] += 1
            except KeyError:
                dcount[cell] = 1
    num = [dcount[k] for k in dcount]
    num.sort(reverse = True)
    dlist = {}
    for n in num:
        for k in dcount:
            if dcount[k] == n:
                dlist[k] = n
                dcount[k] = -1
    return dlist

def list_to_tree(l):
    res = [[] for _ in range(10)]
    for i in l:
        res[int(i[:2]) - 1].append(i)
    return res

def get_people_history_foods(sql_obj,table,phone_num):
    FOOD_INDEX=4
    select_order = "SELECT * FROM {} WHERE mem_mobile='{}';".format(table,phone_num)
    result = sql_obj.select_data(select_order)
    history_food_list = []
    for i in result:
        if(len(i[4])!=2):  # 有的菜号是两位
            if(i[4][0]=='0'):
                history_food_list.append(i[4][1:])
            else:
                history_food_list.append(i[4])
    return history_food_list

class fp_growth:
    @staticmethod
    def run(people_num, phone_num):
        fp_tree_path = "./data/fp_tree.txt"
        if not os.path.exists(fp_tree_path):
            data = []
            with open("./data/code_items_table.csv", "r") as f:
                lines = f.readlines()
                for line in lines:
                    line = line[:-1]
                    cells = line.split(",")[2:]
                    data.append(cells)
                dlist = preprocess_data(data)
                dlist = list(dlist.keys())
                root, uid_nodes = build_tree(data, dlist)
                save_fp_tree(root, uid_nodes)
        recommend_obj = recommend.Recommend('./data/similarity_matrix.csv', './data/item_price.csv',
                                './data/people_average_num_food.csv', './data/people_average_num_type.csv',
                                './data/sale_rank.csv', './data/food_rate.csv')
        food_type_num = recommend_obj.get_each_class_food_type_num(people_num)
        food_num = recommend_obj.get_each_class_food_num(people_num)
        sql_obj = mmySQL("localhost","root","admin","data")
        history_food_list = recommend.get_people_history_foods(sql_obj, 'qinghua_huiyuan_caipin', phone_num)
        root, uid_nodes = load_fp_tree()
        res = fp_recommend(root, uid_nodes, people_num, food_num, history_food_list)
        final_result = []
        for r in res:
            l = list_to_tree(r[1])
            fr = recommend_obj.get_final_recommend_list(l, food_num,)
            final_result.append(fr)
        res = [r[1:] for r in final_result[0]]
        return res

if __name__ == "__main__":
    res = FPGROWTH.run(6)
    print(res)
    # data = []
    # # with open("../data/code_items_table.csv", "r") as f:
    # #tlist = ['020202', '081383', '020201', '010101', '040402', '030314', '030312', '030311', '050507', '030313']
    # recommend_obj = recommend.Recommend('../data/similarity_matrix.csv', '../data/item_price.csv',
    #                            '../data/people_average_num_food.csv', '../data/people_average_num_type.csv',
    #                            '../data/sale_rank.csv', '../data/food_rate.csv')
    # food_type_num = recommend_obj.get_each_class_food_type_num(5)

    # #     lines = f.readlines()
    # #     for line in lines:
    # #         line = line[:-1]
    # #         cells = line.split(",")[2:]
    # #         data.append(cells)
    # #     dlist = preprocess_data(data)
    # #     dlist = list(dlist.keys())
    # #     root, uid_nodes = build_tree(data, dlist)
    # #     save_fp_tree(root, uid_nodes)
    #     # res = recommand(root, uid_nodes, dlist, 3, food_num, tlist)
    #     # print(res)
    # food_num = recommend_obj.get_each_class_food_num(5)
    # print(food_num, food_type_num)
    # root, uid_nodes = load_fp_tree()
    # res = fp_recommend(root, uid_nodes, food_num)
    # print(uid_nodes.keys())
    # for r in res:
    #     l = list_to_tree(r[0])
    #     print(l)
    #     #fr = recommend_obj.get_final_recommend_list(l, food_num)
    #     #print(fr)
    